<template>
  <div class="singer-detail" id="singerDetail" ref="singerDetailRef" v-loading="isLoading">
    <div class="header">
      <img :src="picUrl" alt="">
      <div class="right">
        <span class="singer-name">
          {{name}}
        </span>
        <span class="singer-nickname">
          {{aliasStr}}
        </span>
        <div class="sub">
          <i class="iconfont iconshoucang1"/>
          收藏
        </div>
        <div class="count">
          <span>单曲数:{{musicSize}}</span>
          <span>专辑数:{{albumSize}}</span>
          <span>MV数:{{mvSize}}</span>
        </div>
      </div>
    </div>
    <Tabs v-model="target">
      <TabPane label="专辑" name="album">
        <HotSongs
          :songsList="songs"
          :isHot = 'true'
        />
        <template v-if="hotAlbums.length">
          <HotSongs
            v-for="item of hotAlbums"
            :songsList="item.songsList"
            :albumDetail = '{
            id: item.id,
            name: item.name,
            picUrl: item.picUrl,
            pub: item.pub
          }'
            :key="item"
          />
        </template>
      </TabPane>
      <TabPane label="MV" name="mv">
        <ul class="mv-list" v-if="mvs.length">
          <li
            class="mv-item"
            v-for="mvItem of mvs"
            @click="selectMv(mvItem.id)"
            :key="mvItem"
          >
            <MvItem :mvItem="mvItem"/>
          </li>
        </ul>
      </TabPane>
      <TabPane label="歌手详情" name="singerDetail">
        <Desc :introduction="introduction"/>
      </TabPane>
      <TabPane label="相似歌手" name="simiSinger">
        <ul class="singer-list" v-if="simiSingers.length">
          <li
            class="singer"
            v-for="singer of simiSingers"
            @click="selectSinger(singer.id)"
            :key="singer"
          >
            <Singer :singer="singer"/>
          </li>
        </ul>
      </TabPane>
    </Tabs>
  </div>
</template>

<script lang="ts">
import { getSingerInfo, getAlbums, getSimiSinger, getSingerMvs, getSingerDesc } from '@/api/artists'
import { onMounted, ref, reactive, toRefs, nextTick, watch } from 'vue'
import { on, off } from '@/utils/dom'
import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router'
import { SINGER_ALBUM_LIMIT, SINGER_MV_LIMIT } from '@/utils/constant'
import { debounce } from '@/utils/util'
import HotSongs from '@/views/singerDetail/components/HotSongs.vue'
import MvItem from '@/views/singerDetail/components/MVItem.vue'
import Desc from '@/views/singerDetail/components/Desc.vue'
import Singer from '@/views/singerDetail/components/Singer.vue'

interface Song {
  id: number;
  duration: string;
  name: string;
  aliasStr: string;
  mv: number;
}

interface SingerInfo {
  id: number;
  name: string;
  aliasStr: string;
  picUrl: string;
  musicSize: number;
  albumSize: number;
  mvSize: number;
  briefDesc: string;
}

export default {
  name: 'Index',
  components: {
    HotSongs,
    MvItem,
    Desc,
    Singer
  },
  setup () {
    const route = useRoute()
    const router = useRouter()
    const singerDetailRef = ref<Element | null>(null)
    const isLoading = ref<boolean>(false)
    let singerInfo = reactive<SingerInfo>({
      id: -1,
      name: '',
      briefDesc: '',
      picUrl: '',
      musicSize: 0,
      albumSize: 0,
      mvSize: 0,
      aliasStr: ''
    })
    const songs = ref<Song[]>([])
    const target = ref<string>('album')
    const limit = ref<number>(SINGER_ALBUM_LIMIT)
    const mvLimit = ref<number>(SINGER_MV_LIMIT)
    const mvs = ref<any[]>([])
    const mvMore = ref<boolean>(false)
    const offset = ref<number>(0)
    const hotAlbums = ref([])
    const isMore = ref<boolean>(false)
    const introduction = ref<any[]>([])
    const simiSingers = ref<any[]>([])
    const init = async (id) => {
      isLoading.value = true
      offset.value = 0
      let mvOffset = 0
      try {
        const { singerInfo: info, hotSongsList: list } = await getSingerInfo({ id })
        const { hotAlbumsList, more } = await getAlbums({ id, limit: limit.value, offset: offset.value })
        const { mvs: mvlist, hasMore } = await getSingerMvs({ id, limit: mvLimit.value, offset: mvOffset })
        const { data: { introduction: intro } } = await getSingerDesc(id)
        const { data: { artists } } = await getSimiSinger(id)
        singerInfo = Object.assign(singerInfo, info)
        songs.value = [...list]
        hotAlbums.value = [...hotAlbumsList]
        isMore.value = more
        mvs.value = mvlist
        mvMore.value = hasMore
        introduction.value = intro
        simiSingers.value = artists.map(item => ({ id: item.id, name: item.name, picUrl: item.picUrl }))
        while (mvMore.value) {
          mvOffset++
          const { mvs: mvMorelist, hasMore } = await getSingerMvs({ id, limit: mvLimit.value, offset: mvOffset })
          mvMore.value = hasMore
          mvs.value = mvs.value.concat(mvMorelist)
        }
      } catch (e) {
        isLoading.value = false
        console.log(e)
      }
      isLoading.value = false
    }

    const updateAlbums = debounce(async (event) => {
      const clientHeight = event.target.clientHeight
      const scrollHeight = event.target.scrollHeight
      const scrollTop = event.target.scrollTop
      if (scrollHeight - scrollTop - clientHeight <= 100 && isMore.value) {
        isLoading.value = true
        offset.value++
        try {
          const { hotAlbumsList, more } = await getAlbums({ id: route.params.id, limit: limit.value, offset: offset.value })
          isMore.value = more
          hotAlbums.value = hotAlbums.value.concat(hotAlbumsList)
        } catch (e) {
          isLoading.value = false
          console.log(e)
        }
        isLoading.value = false
      }
    }, 300)

    const selectMv = (id) => {
      router.push({ name: 'video', params: { id } })
    }

    const selectSinger = (id) => {
      router.push({ name: 'singerDetail', params: { id } })
      singerDetailRef.value.scrollTop = 0
    }

    watch(() => target.value, () => {
      nextTick(() => {
        if (target.value === 'album') {
          on(document.querySelector('#singerDetail') as HTMLElement, 'scroll', updateAlbums)
        } else {
          off(document.querySelector('#singerDetail') as HTMLElement, 'scroll', updateAlbums)
        }
      })
    }, {
      immediate: true
    })

    onBeforeRouteUpdate((to) => {
      init(to.params.id)
    })

    onMounted(() => {
      init(route.params.id)
    })
    return {
      isLoading,
      singerDetailRef,
      target,
      songs,
      hotAlbums,
      isMore,
      mvs,
      simiSingers,
      introduction,
      ...toRefs(singerInfo),
      selectSinger,
      selectMv
    }
  }
}
</script>

<style lang="scss" scoped>
.singer-detail {
  height: 100%;
  width: 100%;
  box-sizing: border-box;
  overflow-x: hidden;
  overflow-y: scroll;
  padding: 30px 20px 0 20px;

  .header {
    display: flex;
    flex-wrap: nowrap;
    flex-direction: row;

    >img {
      width: 180px;
      height: 180px;
      border-radius: 5px;
      margin-right: 15px;
      border: 1px solid #D0D0D0;
      box-sizing: border-box;
    }

    .right {
      flex: 1;
      display: flex;
      flex-direction: column;
      font-size: 13px;
      line-height: 1.2;

      .singer-name {
        font-size: 20px;
        font-weight: bold;
        padding-bottom: 14px;
        padding-top: 5px;
        align-self: baseline;
      }

      .singer-nickname {
        padding-bottom: 14px;
        font-size: 14px;
        align-self: baseline;
      }

      .sub {
        display: inline-block;
        margin-bottom: 15px;
        font-size: 15px;
        padding: 5px 12px;
        border: 1px solid #D0D0D0;
        border-radius: 15px;
        cursor: pointer;
        align-self: baseline;
        color: #666666;

        >i {
          font-size: 18px;
          padding-right: 3px;
        }
      }

      .count {
        display: flex;
        flex-direction: row;
        color: #666666;

        span ~ span {
          padding-left: 15px;
        }
      }
    }
  }

  .mv-list {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-start;

    .mv-item {
      flex: 0 0 24%;
      margin-bottom: 20px;
      margin-right: 10px;
      overflow: hidden;
      cursor: pointer;
    }
  }

  .singer-list {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-start;

    .singer {
      flex: 0 0 19%;
      margin-bottom: 25px;
      margin-right: 10px;
      cursor: pointer;
      overflow: hidden;
    }
  }
}
</style>
